From dec435003fd10fc92b1dc4c1fbdf3e3e0a130501 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Mon, 21 Mar 2005 09:51:50 +0000 Subject: [PATCH] bitkeeper revision 1.1159.273.4 (423e9936-Gs_rM0rC9UWa8TA2293kA) Fix floppy driver on Xen -- vmalloc/vfree are unsafe because of the context that the fd_dma functions may get called from. Signed-off-by: Keir Fraser --- .../include/asm-xen/asm-i386/floppy.h | 119 ++++-------------- 1 file changed, 22 insertions(+), 97 deletions(-) diff --git a/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/floppy.h b/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/floppy.h index ff838f21fb..2d5dd220ad 100644 --- a/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/floppy.h +++ b/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/floppy.h @@ -28,10 +28,14 @@ #define fd_enable_irq() enable_irq(FLOPPY_IRQ) #define fd_disable_irq() disable_irq(FLOPPY_IRQ) #define fd_free_irq() free_irq(FLOPPY_IRQ, NULL) -#define fd_get_dma_residue() vdma_get_dma_residue(FLOPPY_DMA) -#define fd_dma_mem_alloc(size) vdma_mem_alloc(size) -#define fd_dma_mem_free(addr, size) vdma_mem_free(addr, size) +#define fd_get_dma_residue() (virtual_dma_count + virtual_dma_residue) #define fd_dma_setup(addr, size, mode, io) vdma_dma_setup(addr, size, mode, io) +/* + * Do not use vmalloc/vfree: floppy_release_irq_and_dma() gets called from + * softirq context via motor_off_callback. A generic bug we happen to trigger. + */ +#define fd_dma_mem_alloc(size) __get_free_pages(GFP_KERNEL, get_order(size)) +#define fd_dma_mem_free(addr, size) free_pages(addr, get_order(size)) static int virtual_dma_count; static int virtual_dma_residue; @@ -42,99 +46,36 @@ static int doing_pdma; static irqreturn_t floppy_hardint(int irq, void *dev_id, struct pt_regs * regs) { register unsigned char st; + register int lcount; + register char *lptr; -#undef TRACE_FLPY_INT -#define NO_FLOPPY_ASSEMBLER - -#ifdef TRACE_FLPY_INT - static int calls=0; - static int bytes=0; - static int dma_wait=0; -#endif if (!doing_pdma) return floppy_interrupt(irq, dev_id, regs); -#ifdef TRACE_FLPY_INT - if(!calls) - bytes = virtual_dma_count; -#endif - -#ifndef NO_FLOPPY_ASSEMBLER - __asm__ ( - "testl %1,%1" - "je 3f" -"1: inb %w4,%b0" - "andb $160,%b0" - "cmpb $160,%b0" - "jne 2f" - "incw %w4" - "testl %3,%3" - "jne 4f" - "inb %w4,%b0" - "movb %0,(%2)" - "jmp 5f" -"4: movb (%2),%0" - "outb %b0,%w4" -"5: decw %w4" - "outb %0,$0x80" - "decl %1" - "incl %2" - "testl %1,%1" - "jne 1b" -"3: inb %w4,%b0" -"2: " - : "=a" ((char) st), - "=c" ((long) virtual_dma_count), - "=S" ((long) virtual_dma_addr) - : "b" ((long) virtual_dma_mode), - "d" ((short) virtual_dma_port+4), - "1" ((long) virtual_dma_count), - "2" ((long) virtual_dma_addr)); -#else - { - register int lcount; - register char *lptr; - - st = 1; - for(lcount=virtual_dma_count, lptr=virtual_dma_addr; - lcount; lcount--, lptr++) { - st=inb(virtual_dma_port+4) & 0xa0 ; - if(st != 0xa0) - break; - if(virtual_dma_mode) - outb_p(*lptr, virtual_dma_port+5); - else - *lptr = inb_p(virtual_dma_port+5); - } - virtual_dma_count = lcount; - virtual_dma_addr = lptr; - st = inb(virtual_dma_port+4); + st = 1; + for(lcount=virtual_dma_count, lptr=virtual_dma_addr; + lcount; lcount--, lptr++) { + st=inb(virtual_dma_port+4) & 0xa0 ; + if(st != 0xa0) + break; + if(virtual_dma_mode) + outb_p(*lptr, virtual_dma_port+5); + else + *lptr = inb_p(virtual_dma_port+5); } -#endif + virtual_dma_count = lcount; + virtual_dma_addr = lptr; + st = inb(virtual_dma_port+4); -#ifdef TRACE_FLPY_INT - calls++; -#endif if(st == 0x20) return IRQ_HANDLED; if(!(st & 0x20)) { virtual_dma_residue += virtual_dma_count; virtual_dma_count=0; -#ifdef TRACE_FLPY_INT - printk("count=%x, residue=%x calls=%d bytes=%d dma_wait=%d\n", - virtual_dma_count, virtual_dma_residue, calls, bytes, - dma_wait); - calls = 0; - dma_wait=0; -#endif doing_pdma = 0; floppy_interrupt(irq, dev_id, regs); return IRQ_HANDLED; } -#ifdef TRACE_FLPY_INT - if(!virtual_dma_count) - dma_wait++; -#endif return IRQ_HANDLED; } @@ -145,28 +86,12 @@ static void fd_disable_dma(void) virtual_dma_count=0; } -static int vdma_get_dma_residue(unsigned int dummy) -{ - return virtual_dma_count + virtual_dma_residue; -} - static int fd_request_irq(void) { return request_irq(FLOPPY_IRQ, floppy_hardint,SA_INTERRUPT, "floppy", NULL); } -static unsigned long vdma_mem_alloc(unsigned long size) -{ - return (unsigned long) vmalloc(size); - -} - -static void vdma_mem_free(unsigned long addr, unsigned long size) -{ - vfree((void *)addr); -} - static int vdma_dma_setup(char *addr, unsigned long size, int mode, int io) { doing_pdma = 1; -- 2.30.2